/**
 * @author   Ivan Andonov
 * @email:   ivan.andonov[at]gmail[dot]com
 * 
 * @require  sjs, sjs.ShortcutCall, sjs.Delegate, sjs.Events
 * @use      sjs.Strings, sjs.Styles, sjs.Keyboard, sjs.Utils, sjs.Objects, sjs.Ajax
 * @optional 
 **/

(function() {
	
	sjs.create('sjs.Debug', {
		
		// PUBLIC STATIC VARS
		consoleWraped : false,
		consoleLog : null,
		buffer : 500,
		areaBuffer : 500,
		showAlert : false,
		logErrors : true,
		showTime : true,
		showMsgNum : true,
		jsError : 'jsError',
		id : 'debug',
		mode : 'testing',
		//mode : 'online',
		
		// PUBLIC STATIC METHODS
		log : function(msg, showAlert) {
			var obj = { 
				time:new Date().getTime(),
				msg:msg
			};
			if (inited && this.mode == 'testing') {
				this.showMsg(obj);
			}
			data.push(obj);
			if (data.length > this.buffer) {
				data.shift();
			}
			if (showAlert || (showAlert !== false && this.showAlert)) {
				alert((this.showTime ? this.getTimeStr(obj.time)+' - ' : '')+obj.msg);
			}
		},
		
		logError : function(error, props) {
			if (this.logErrors && sjs.Ajax) {
				$delegate(sjs.Ajax, 'call', $delegate(this, 'sendError', this.getLastMessages()+'\n'+error, props))();
			}
			this.log(error);
		},
		
		clear : function() {
			data = [];
			$html(this.id, '');
		},
		
		getTimeStr : function(time) {
			var timer = (time-initTime);
			var milisecs = sjs.Strings.zeroPad(timer%1000, 3);
			var secs = sjs.Strings.zeroPad((timer-milisecs)/1000%60, 2);
			var mins = sjs.Strings.zeroPad(Math.floor((timer-milisecs)/1000/60), 2);
			return mins+':'+secs+':'+milisecs;
		},
		
		getLastMessages : function(num) {
			if (!num) {
				num = 5;
			}
			var logs = data.slice(Math.max(data.length-1-num, 0), data.length-1);
			var str = '';
			var len = logs.length;
			for (var i = 0; i < len; i++) {
				str += (!i ? '' : '\n')+this.getTimeStr(logs[i].time)+': '+logs[i].msg;
			}
			return str;
		},

		// PRIVATE STATIC METHODS
		
		
		initDebugger : function() {
			$log('initDebugger');
			if (this.mode == 'testing') {
				bg_node = document.createElement('div');
				bg_node.setAttribute('id', this.id+'_bg');
				debug_node = document.createElement('div');
				debug_node.setAttribute('id', this.id);
				$body().appendChild(bg_node);
				$body().appendChild(debug_node);
				// debug style
				if (sjs.Utils.isIE()) {
					var textStyle_obj = sjs.Strings.cssToObj(textStyle);
					sjs.Objects.each(textStyle_obj, function(prop, value, obj) {
						$style(sjs.Debug.id, prop, value);
					});
					var textBgStyle_obj = sjs.Strings.cssToObj(textBgStyle);
					sjs.Objects.each(textBgStyle_obj, function(prop, value, obj) {
						$style(sjs.Debug.id+'_bg', prop, value);
					});
				} else {
					var styleText = ' #'+this.id+' '+textStyle+'\n';
					styleText += ' #'+this.id+'_bg '+textBgStyle+'\n';
					var styleNode = document.createElement('style');
					styleNode.setAttribute('type', 'text/css');
					var styleTextNode = document.createTextNode(styleText);
					styleNode.appendChild(styleTextNode);
					$body().appendChild(styleNode);
				}
				sjs.Events.addEvent('document', 'onkeydown', $delegate(this, 'switchArea'));
				var len = data.length;
				for (var i = 0; i < len; i++) {
					this.showMsg(data[i]);
				}
			}
			inited = true;
		},
		
		showMsg : function(obj) {
			msgNum++;
			var p = document.createElement('p');
			var d = debug_node; 
			if (d.childNodes.length) {
				d.insertBefore(p, d.childNodes[0]);
			} else {
				d.appendChild(p);
			}
			
			var str = (this.showMsgNum ? msgNum+': ' : '')+(this.showTime ? this.getTimeStr(obj.time)+' - ' : '')+sjs.Strings.htmlEntities(obj.msg);
			p.innerHTML = str;
			$style(p, [['lineHeight', '100%'],['margin', '0'],['fontSize', '10px'],['padding', '.5em 0 0 0']]);
			
			if (this.consoleWraped) {
				this.consoleLog(str);
			}
			
			while (d.childNodes.length > this.areaBuffer) {
				d.removeChild(d.lastChild);
			}
		},
		
		switchArea : function(e) {
			e = window.event ? window.event : e;
			if ($keyboard !== null) {
				if (e.keyCode == $keyboard('ESCAPE')) {
					if ($style(this.id, 'display') != 'block') {
						$style(this.id, 'display', 'block');
						$style(this.id+'_bg', 'display', 'block');
						scrollId = sjs.Events.addEvent('window', 'onscroll', $delegate(this, 'update'));
						resizeId = sjs.Events.addEvent('window', 'onresize', $delegate(this, 'update'));
						this.update();
						if (sjs.Utils.isIE6()) {
							sjs.Utils.hideSelects();
						}
					} else {
						$style(this.id, 'display', 'none');
						$style(this.id+'_bg', 'display', 'none');
						sjs.Events.removeEvent('window', 'onscroll', scrollId);
						sjs.Events.removeEvent('window', 'onresize', resizeId);
						if (sjs.Utils.isIE6()) {
							sjs.Utils.showSelects();
						}
					}
				}
			}
		},
		
		update : function(e) {
			//$style(this.id+'_bg', [['left', sjs.Utils.getPageXScroll()+'px'], ['top', sjs.Utils.getPageYScroll()+'px']]);
			$style(this.id+'_bg', 'height', sjs.Utils.getDocumentHeight()+'px');
			$style(this.id+'_bg', 'width', sjs.Utils.getDocumentWidth()+'px');
		},
		
		sendError : function(error, props) {
			var errAjax = new sjs.Ajax();
			if (!props) {
				props = {};
			}
			props.page = window.location.href;
			props.error = error;
			errAjax.post((sjs.base || '')+this.jsError, props, null, null, true);
		}
		
	});
	
	// PRIVATE STATIC VARS
	var initTime = new Date().getTime();
	var data = [];
	var inited = false;
	var msgNum = 0;
	var scrollId = null;
	var resizeId = null;
	var bg_node = null;
	var debug_node = null;
	// style
	var textStyle = '{ position:absolute; display:none; left:0; top:0; margin:0; padding:0; width:100%; height:100%; background:white; z-index:99999; text-align:left; font:14px Verdana,Arial,sans-serif; color:black; }';
	var textBgStyle = '{ position:absolute; display:none; left:0; top:0; margin:0; padding:0; width:100%; height:100%; background:white; z-index:99998; }';
	
	// shortcuts
	if ($shortcut) {
		$shortcut('log', sjs.Debug, 'log');
		$shortcut('logError', sjs.Debug, 'logError');
	}

	// firebug console integration
	if (window.console && window.console.log) {
		sjs.Debug.consoleWraped = true;
		sjs.Debug.consoleLog = $delegate(window.console, window.console.log);
	}
	if (!window.console) {
		window.console = {}
	}
	window.console.log = $delegate(sjs.Debug, 'log');

	// onlaod
	sjs.Events.addEvent('window', 'onload', $delegate(sjs.Debug, 'initDebugger'));
	
})();